package com.hnx.admin.system.service.impl;

import com.hnx.admin.api.service.menu.MenuCacheAPI;
import com.hnx.admin.jwt.JwtUtil;
import com.hnx.admin.redis.RedisCache;
import com.hnx.admin.security.utils.SecurityUtil;
import com.hnx.admin.system.domain.convert.menu.MenuConvert;
import com.hnx.admin.system.domain.dto.menu.MenuDTO;
import com.hnx.admin.system.domain.vo.menu.MenuVO;
import com.hnx.admin.system.domain.vo.menu.MetaVO;
import com.hnx.admin.system.domain.vo.menu.RouterVO;
import com.hnx.admin.system.domain.vo.user.UserDetailVO;
import com.hnx.admin.system.domain.vo.user.UserVO;
import com.hnx.admin.system.mapper.menu.MenuMapper;
import com.hnx.admin.system.service.MenuService;
import com.hnx.admin.utils.ServletUtil;
import com.hnx.admin.web.json.ResultJson;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/*
项目名称： core
创 建 人: 倔强的头发
创建日期： 2025/6/1   20:35:03 
描   述：
*/
@Service
@RequiredArgsConstructor
public class MenuServiceImpl implements MenuService, MenuCacheAPI {
    private final MenuMapper menuMapper;
    private final MenuConvert menuConvert;
    private final RedisCache redisCache;
    private final JwtUtil jwtUtil;
    @Override
    public Set<String> getPermissions(UserVO user) {
        Set<String> permission = new HashSet<>();
        if (user.isAdmin()) {
            permission.add("*:*:*");
        }
        return permission;
    }
    /*
    * 获取路由菜单列表
    * */
    private List<MenuDTO> getMenuList(){
        HttpServletRequest request = ServletUtil.getRequest();
        String uuid = jwtUtil.getUuid(request);
        if(StringUtils.hasText(uuid)) {
         List<MenuDTO> list = redisCache.getCacheList(SYS_ROUTERS_KEY+uuid, MenuDTO.class).orElseGet(()->{
                UserDetailVO userDetailVO = (UserDetailVO) SecurityUtil.getPrincipal();
                UserVO userVO = userDetailVO.getUserVO();
                List<MenuDTO> menus = null;
                if (userVO.isAdmin()) {
                    menus = menuMapper.selectMenuTreeAll();
                } else {
                    menus = menuMapper.selectMenuTreeByUserId(userVO.getUserId());
                }
                redisCache.setCacheList(SYS_ROUTERS_KEY+uuid, menus,2,  TimeUnit.HOURS);
                return menus;
            });
         return list;
        }
        return null;
    }
    private List<RouterVO> treeRouters() {
      List<MenuDTO> menus = getMenuList();
      if(menus == null){
          return null;
      }
//        redisCache.setCacheList(getRoutersKey(userVO.getUserId()), menus,2,  TimeUnit.HOURS);
       return treeBuild(menus);
    }

    @Override
    public ResultJson selectMenu() {
        List<RouterVO> routerVOS = treeRouters();

//        if(StringUtils.hasText(uuid)){
//            List<RouterVO> list = redisCache.getCacheList(getRoutersKey(uuid), RouterVO.class).orElseGet(this::treeRouters);
            return ResultJson.success().add("data", routerVOS);
//        }
//        return ResultJson.fail();
    }
    private RouterVO ConvertRouter(MenuVO menu){
        RouterVO routerVO = new RouterVO();
        routerVO.setHidden("1".equals(menu.getVisible()));
        routerVO.setName(StringUtils.capitalize(StringUtils.hasText(menu.getRouteName())?menu.getRouteName():menu.getPath()));
        routerVO.setPath(menu.getMenuType().equals(TYPE_DIR) && menu.getParentId() == 0l?"/" + menu.getPath():menu.getPath());
        routerVO.setMeta(new MetaVO(menu.getMenuName(), menu.getIcon(), "1".equals(menu.getIsCache()), menu.getPath()));
        routerVO.setComponent(getComponent(menu));
        if(menu.getMenuType().equals(TYPE_DIR) && menu.getChildren() != null && menu.getChildren().size() > 0){
            routerVO.setRedirect("noRedirect");
            routerVO.setAlwaysShow(true);
            List<RouterVO> list = menu.getChildren().stream().collect(Collectors.mapping(m->ConvertRouter(m), Collectors.toList()));
            routerVO.setChildren(list);
        }
        return routerVO;
    }
    private List<RouterVO> treeBuild(List<MenuDTO> list) {

        List<MenuVO> trees = menuConvert.toVOList(list);
        Map<Long,List<MenuVO>> map = trees.stream().sorted(Comparator.comparing(MenuVO::getOrderNum)).collect(Collectors.groupingBy(MenuVO::getParentId));
        trees.forEach(menu -> menu.setChildren(map.get(menu.getMenuId())));
        return trees.stream().filter(n->n.getParentId() ==0l).sorted(Comparator.comparing(MenuVO::getOrderNum)).collect(Collectors.mapping(this::ConvertRouter, Collectors.toList()));
    }
    /**
     * 内链域名特殊字符替换
     *
     * @return 替换后的内链域名
     */
    public String innerLinkReplaceEach(String path)
    {
        return org.apache.commons.lang3.StringUtils.replaceEach(path, new String[] { HTTP, HTTPS, WWW, ".", ":" },
                new String[] { "", "", "", "/", "/" });
    }

    /**
     * 获取组件信息
     *
     * @param menu 菜单信息
     * @return 组件信息
     */
    public String getComponent(MenuVO menu)
    {
        String component = LAYOUT;
        if (StringUtils.hasText(menu.getComponent()) && !isMenuFrame(menu))
        {
            component = menu.getComponent();
        }
        else if (StringUtils.isEmpty(menu.getComponent()) && menu.getParentId().intValue() != 0 && isInnerLink(menu))
        {
            component = INNER_LINK;
        }
        else if (StringUtils.isEmpty(menu.getComponent()) && isParentView(menu))
        {
            component = PARENT_VIEW;
        }
        return component;
    }
    /**
     * 是否为菜单内部跳转
     *
     * @param menu 菜单信息
     * @return 结果
     */
    public boolean isMenuFrame(MenuVO menu)
    {
        return menu.getParentId().intValue() == 0 && TYPE_MENU.equals(menu.getMenuType())
                && menu.getIsFrame().equals(NO_FRAME);
    }
    /**
     * 是否为内链组件
     *
     * @param menu 菜单信息
     * @return 结果
     */
    public boolean isInnerLink(MenuVO menu) {
        return menu.getIsFrame().equals(NO_FRAME) && ishttp(menu.getPath());
    }

    /**
     * 是否为parent_view组件
     *
     * @param menu 菜单信息
     * @return 结果
     */
    public boolean isParentView(MenuVO menu) {
        return menu.getParentId().intValue() != 0 && TYPE_DIR.equals(menu.getMenuType());
    }
}
